export interface AjaxConfig {
    url: string;
    type: string;
    withCredentials: boolean,
    headers?: Object,
    transformRequest: Function,
    transformResponse: Function,
    baseURL?: string
    timeout?: Number,
    data?: Object | string,
    params?: Object | string,
}
export function ajax(config: AjaxConfig): Promise<any> {
    var timestamp = (new Date()).getTime()
    parseData(config);
    return new Promise((resolve, reject) => {
        var http: XMLHttpRequest = new XMLHttpRequest();
        http.onreadystatechange = function () {
            if (http.readyState == 4 && http.status == 200) {
                resolve(config.transformResponse(JSON.parse(http.responseText)))
            } else if (http.readyState == 4 && http.status != 200){
                reject(config.transformResponse(JSON.parse(http.responseText)))
            } else {
                if (((new Date()).getTime() - timestamp)>config.timeout) {
                    reject(new Error('请求超时'))
                }
            }
        }
        http.open(config.type, config.baseURL + config.url + config.params, true);
        http.withCredentials = config.withCredentials;
        setHttp(http, config)
        http.send(config.data.toString());
    })
}

function setHttp(http: XMLHttpRequest, option: AjaxConfig) {
    for (let prop in option.headers){
        http.setRequestHeader(prop, option.headers[prop])
    }
}

function parseData(option) {
    if (option.data) {
        option.data = option.transformRequest(option.data);
        let text: string = "";
        let index: number = 1
        for (let lode in option.data) {
            if (index) {
                text += `${lode}=${option.data[lode]}`;
                index = 0
            } else {
                text += `&${lode}=${option.data[lode]}`;
            }
        }
        option.data = text
    } else {
        option.data=""
    }
    if (option.params) {
        option.params = option.transformRequest(option.params);
        let text: string = "";
        let index: number = 1
        for (let lode in option.params) {
            if (index) {
                text += `?${lode}=${option.params[lode]}`;
                index = 0
            } else {
                text += `&${lode}=${option.params[lode]}`;
            }
        }
        option.params = text
    } else {
        option.params = ""
    }
}